package com.wq.payunion.oauth2.useroauth2.utils;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @Author: wangqiang20995
 * @Date:2018 年 9 月 10 日 0010
 * @Description:
 * @Resource:
 */
@Component
public class HttpCommunication {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private CloseableHttpClient simpleHttpClient;
    private ExecutorService requestExecutor;
    private static final int CORE_POOL_SIZE = 10;
    private int maxPoolSize;//最大线程数
    private long idleThreadKeepAlive;
    private BlockingDeque<Runnable> blockingDeque;//阻塞队列需要是线程安全的
    private ThreadFactory threadFactory;
    private SSLContext simpleSslContext;//完全信任服务端证书
    private SSLContext complexSslContext;//需要验证服务端证书
    private String defaultCharset = "UTF-8";

    private HttpCommunication(int maxPoolSize, long idleThreadKeepAlive, BlockingDeque<Runnable> blockingDeque) {
        this.threadFactory = Executors.defaultThreadFactory();
        requestExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
                maxPoolSize,
                idleThreadKeepAlive,
                TimeUnit.MILLISECONDS,
                blockingDeque,
                threadFactory);
//        synchronized (this) {
        this.simpleHttpClient = simpleHttpsClient();
//        }
    }

    public HttpCommunication() {
        this(10,10000,new LinkedBlockingDeque<>(100));
    }

    public String doFullTrustHttpsPostRequest(String url, Map<String, String> param) {
        if (StringUtils.isEmpty(url)) {
            logger.error("请求地址不能为空");
            return null;
        }
        HttpPost post = new HttpPost(url);
        HttpResponse response = null;
//        post.setHeader("Content-Type","application/json");
        List<NameValuePair> paramsList = new ArrayList<>(param.size());
        if (param.size() > 0) {
            Iterator<Map.Entry<String, String>> iterator = param.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, String> paramPair = iterator.next();
                paramsList.add(new BasicNameValuePair(paramPair.getKey(), paramPair.getValue()));
            }
            UrlEncodedFormEntity formEntity = null;
            try {
                formEntity = new UrlEncodedFormEntity(paramsList, defaultCharset);
            } catch (UnsupportedEncodingException e) {
                logger.error(e.getMessage());
            }

            logger.info("发送Https请求，地址[{}],参数[{}]", url, paramsList);
            if (formEntity == null) {
                logger.error("准备发送数据包异常");
                return null;
            }
            post.setEntity(formEntity);
            InputStream inputStream = null;
            try {
                response = this.simpleHttpClient.execute(post);
                inputStream = response.getEntity().getContent();
                String str = prepareResponse(inputStream);
                logger.info("对方服务器返回信息[{}]", str);
                return str;
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        logger.error(e.getMessage(), e);
                    }
                }
            }
        }

        return "";
    }


    /**
     * @Author:wangqiang20995
     * @Datetime:2018 年 9 月 12 日 0012 21:48:10
     * @param: [params]
     * @Description:将map转换为键值对
     **/
    public String transferRequestParams(Map<String, String> params) {
        StringBuilder builder = new StringBuilder();
        if (params.size() == 0) {
            return "";
        }

        Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> param = iterator.next();
            builder.append(param.getKey()).append("=").append(param.getValue()).append("&");
        }

        builder.deleteCharAt(builder.length() - 1);
        return builder.toString();
    }

    private String prepareResponse(InputStream inputStream) throws IOException {
        StringBuilder builder = new StringBuilder();
        BufferedReader reader;

        reader = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        while ((line = reader.readLine()) != null) {
            builder.append(line);
        }

        return builder.toString();
    }

    private CloseableHttpClient simpleHttpsClient() {
        try {
            this.simpleSslContext = new SSLContextBuilder().loadTrustMaterial(null, (chain, authType) -> {
                return true;
            }).build();
            HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
            SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(simpleSslContext, hostnameVerifier);
            return HttpClients.custom().setSSLSocketFactory(socketFactory).build();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    ;


}
